#include "stdafx.h"
#include "BSValue.h"
#include <assert.h>
#include <string>


#define JSON_ASSERT_UNREACHABLE assert( false )
#define JSON_ASSERT( condition ) assert( condition );  // @todo <= change this into an exception throw
#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message );




const BSValue BSValue::null;
const int BSValue::minInt = int( ~((unsigned int)(-1)/2) );
const int BSValue::maxInt = int( (unsigned int)(-1)/2 );
const unsigned int BSValue::maxUInt = (unsigned int)(-1);
//////////////////////////////////
//////////////////////////////////
///////////allocator
ValueAllocator::~ValueAllocator()
{
}

class DefaultValueAllocator : public ValueAllocator
{
public:
	virtual ~DefaultValueAllocator()
	{
	}

	virtual char *makeMemberName( const char *memberName )
	{
		return duplicateStringValue( memberName );
	}

	virtual void releaseMemberName( char *memberName )
	{
		releaseStringValue( memberName );
	}

	virtual char *duplicateStringValue( const char *value, 
		unsigned int length = unknown )
	{
		//@todo invesgate this old optimization
		//if ( !value  ||  value[0] == 0 )
		//   return 0;

		if ( length == unknown )
			length = (unsigned int)strlen(value);
		char *newString = static_cast<char *>( malloc( length + 1 ) );
		memcpy( newString, value, length );
		newString[length] = 0;
		return newString;
	}

	virtual void releaseStringValue( char *value )
	{
		if ( value )
			free( value );
	}
};

static ValueAllocator *&valueAllocator()
{
	static DefaultValueAllocator defaultAllocator;
	static ValueAllocator *valueAllocator = &defaultAllocator;
	return valueAllocator;
}

static struct DummyValueAllocatorInitializer {
	DummyValueAllocatorInitializer() 
	{
		valueAllocator();      // ensure valueAllocator() statics are initialized before main().
	}
} dummyValueAllocatorInitializer;

//////////////////allocator
//////////////////////////////////
//////////////////////////////////

BSValue::BSValue( ValueType type )
	: type_( type )
	, allocated_( 0 )
	
{
	switch ( type )
	{
	case nullValue:
		break;
	case intValue:
	case uintValue:
		value_.int_ = 0;
		break;
	case realValue:
		value_.real_ = 0.0;
		break;
	case stringValue:
		value_.string_ = 0;
		break;
	case arrayValue:
		value_.array_ = new ArrayValues();
		break;
	case objectValue:
		value_.map_ = new ObjectValues();
		break;

	case booleanValue:
		value_.bool_ = false;
		break;
	default:
		JSON_ASSERT_UNREACHABLE;
	}
}
BSValue::BSValue( int value )
	: type_( intValue )
{
	value_.int_ = value;
}

BSValue::BSValue( unsigned int value )
	: type_( uintValue )
{
	value_.uint_ = value;
}

BSValue::BSValue( double value )
	: type_( realValue )
{
	value_.real_ = value;
}

BSValue::BSValue( const char *value )
	: type_( stringValue )
	, allocated_( true )
{
	value_.string_ = valueAllocator()->duplicateStringValue( value );
}


BSValue::BSValue( const char *beginValue, 
	const char *endValue )
	: type_( stringValue )
	, allocated_( true )
{
	value_.string_ = valueAllocator()->duplicateStringValue( beginValue, 
    (unsigned int)(endValue - beginValue) );
}



BSValue::BSValue( const std::string &value )
	: type_( stringValue )
	, allocated_( true )
{
	value_.string_ = valueAllocator()->duplicateStringValue( value.c_str(), 
		(unsigned int)value.length() );
}


BSValue::BSValue( bool value )
	: type_( booleanValue )
{
	value_.bool_ = value;
}


BSValue::BSValue( const BSValue &other )
	: type_( other.type_ )
{
	switch ( type_ )
	{
	case nullValue:
	case intValue:
	case uintValue:
	case realValue:
	case booleanValue:
		value_ = other.value_;
		break;
	case stringValue:
		if ( other.value_.string_ )
		{
			value_.string_ = valueAllocator()->duplicateStringValue( other.value_.string_ );
			allocated_ = true;
		}
		else
			value_.string_ = 0;
		break;

	case arrayValue:
		value_.array_ = new ArrayValues( *other.value_.array_);
		break;
	case objectValue:
		value_.map_ = new ObjectValues( *other.value_.map_ );
		break;
	default:
		JSON_ASSERT_UNREACHABLE;
	}
}

BSValue::~BSValue(void)
{
	switch ( type_ )
	{
	case nullValue:
	case intValue:
	case uintValue:
	case realValue:
	case booleanValue:
		break;
	case stringValue:
		if ( allocated_ )
			valueAllocator()->releaseStringValue( value_.string_ );
		break;
	case arrayValue:
		delete value_.array_;
		break;
	case objectValue:
		delete value_.map_;
		break;

	default:
		JSON_ASSERT_UNREACHABLE;
	}

	
}


BSValue & BSValue::operator=(const  BSValue &other )
{
	BSValue temp( other );
	swap( temp );
	return *this;
}

void BSValue::swap( BSValue &other )
{
	ValueType temp = type_;
	type_ = other.type_;
	other.type_ = temp;
	std::swap( value_, other.value_ );
	int temp2 = allocated_;
	allocated_ = other.allocated_;
	other.allocated_ = temp2;
}

ValueType BSValue::type() const
{
	return type_;
}


bool BSValue::operator <( const BSValue &other ) const
{
	int typeDelta = type_ - other.type_;
	//if ( typeDelta )
	//	return typeDelta < 0 ? true : false;
	//wangyan
	JSON_ASSERT(typeDelta==0);
	switch ( type_ )
	{
	case nullValue:
		return false;
	case intValue:
		return value_.int_ < other.value_.int_;
	case uintValue:
		return value_.uint_ < other.value_.uint_;
	case realValue:
		return value_.real_ < other.value_.real_;
	case booleanValue:
		return value_.bool_ < other.value_.bool_;
	case stringValue:
		return ( value_.string_ == 0  &&  other.value_.string_ )
			|| ( other.value_.string_  
			&&  value_.string_  
			&& strcmp( value_.string_, other.value_.string_ ) < 0 );
	case arrayValue:
		{
			int delta = int( value_.array_->size() - other.value_.array_->size() );
			if ( delta )
				return delta < 0;
			return (*value_.array_) < (*other.value_.array_);
		}
	case objectValue:
		{
			int delta = int( value_.map_->size() - other.value_.map_->size() );
			if ( delta )
				return delta < 0;
			return (*value_.map_) < (*other.value_.map_);
		}
	default:
		JSON_ASSERT_UNREACHABLE;
	}
	return 0;  // unreachable
}


bool 
	BSValue::operator <=( const BSValue &other ) const
{
	return !(other > *this);
}

bool 
	BSValue::operator >=( const BSValue &other ) const
{
	return !(*this < other);
}

bool 
	BSValue::operator >( const BSValue &other ) const
{
	return other < *this;
}

bool 
	BSValue::operator ==( const BSValue &other ) const
{
	//if ( type_ != other.type_ )
	// GCC 2.95.3 says:
	// attempt to take address of bit-field structure member `Json::Value::type_'
	// Beats me, but a temp solves the problem.
	int temp = other.type_;
	if ( type_ != temp )
		return false;
	switch ( type_ )
	{
	case nullValue:
		return true;
	case intValue:
		return value_.int_ == other.value_.int_;
	case uintValue:
		return value_.uint_ == other.value_.uint_;
	case realValue:
		return value_.real_ == other.value_.real_;
	case booleanValue:
		return value_.bool_ == other.value_.bool_;
	case stringValue:
		return ( value_.string_ == other.value_.string_ )
			|| ( other.value_.string_  
			&&  value_.string_  
			&& strcmp( value_.string_, other.value_.string_ ) == 0 );
	case arrayValue:
		return value_.array_->size() == other.value_.array_->size()
			&& (*value_.array_) == (*other.value_.array_);
	case objectValue:
		return value_.map_->size() == other.value_.map_->size()
			&& (*value_.map_) == (*other.value_.map_);

	default:
		JSON_ASSERT_UNREACHABLE;
	}
	return 0;  // unreachable
}

bool BSValue::operator !=( const BSValue &other ) const
{
	return !( *this == other );
}


std::string BSValue::asString() const
{
	switch ( type_ )
	{
	case nullValue:
		return "";
	case stringValue:
		return value_.string_ ? value_.string_ : "";
	case booleanValue:
		return value_.bool_ ? "true" : "false";
	case intValue:
	case uintValue:
	case realValue:
	case arrayValue:
	case objectValue:
		 JSON_ASSERT_MESSAGE( false, "Type is not convertible to string" );
	default:
		JSON_ASSERT_UNREACHABLE;
	}
	return ""; // unreachable
}


int BSValue::asInt() const
{
	switch ( type_ )
	{
	case nullValue:
		return 0;
	case intValue:
		return value_.int_;
	case uintValue:
		JSON_ASSERT_MESSAGE( value_.uint_ < (unsigned)maxInt, "integer out of signed integer range" );
		return value_.uint_;
	case realValue:
		JSON_ASSERT_MESSAGE( value_.real_ >= minInt  &&  value_.real_ <= maxInt, "Real out of signed integer range" );
		return int( value_.real_ );
	case booleanValue:
		return value_.bool_ ? 1 : 0;
	case stringValue:
	case arrayValue:
	case objectValue:
		JSON_ASSERT_MESSAGE( false, "Type is not convertible to int" );
	default:
		JSON_ASSERT_UNREACHABLE;
	}
	return 0; // unreachable;
}

unsigned int  BSValue::asUInt() const
{
	switch ( type_ )
	{
	case nullValue:
		return 0;
	case intValue:
		JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
		return value_.int_;
	case uintValue:
		return value_.uint_;
	case realValue:
		JSON_ASSERT_MESSAGE( value_.real_ >= 0  &&  value_.real_ <= maxUInt,  "Real out of unsigned integer range" );
		return (unsigned int)( value_.real_ );
	case booleanValue:
		return value_.bool_ ? 1 : 0;
	case stringValue:
	case arrayValue:
	case objectValue:
		JSON_ASSERT_MESSAGE( false, "Type is not convertible to uint" );
	default:
		JSON_ASSERT_UNREACHABLE;
	}
	return 0; // unreachable;
}

double BSValue::asDouble() const
{
	switch ( type_ )
	{
	case nullValue:
		return 0.0;
	case intValue:
		return value_.int_;
	case uintValue:
		return value_.uint_;
	case realValue:
		return value_.real_;
	case booleanValue:
		return value_.bool_ ? 1.0 : 0.0;
	case stringValue:
	case arrayValue:
	case objectValue:
		JSON_ASSERT_MESSAGE( false, "Type is not convertible to double" );
	default:
		JSON_ASSERT_UNREACHABLE;
	}
	return 0; // unreachable;
}

bool BSValue::asBool() const
{
	switch ( type_ )
	{
	case nullValue:
		return false;
	case intValue:
	case uintValue:
		return value_.int_ != 0;
	case realValue:
		return value_.real_ != 0.0;
	case booleanValue:
		return value_.bool_;
	case stringValue:
		return value_.string_  &&  value_.string_[0] != 0;
	case arrayValue:
		return value_.array_->size() != 0;
	case objectValue:
		return value_.map_->size() != 0;
	default:
		JSON_ASSERT_UNREACHABLE;
	}
	return false; // unreachable;
}


bool BSValue::isNull() const
{
	return type_ == nullValue;
}


bool BSValue::isBool() const
{
	return type_ == booleanValue;
}


bool BSValue::isInt() const
{
	return type_ == intValue;
}


bool BSValue::isUInt() const
{
	return type_ == uintValue;
}


bool BSValue::isIntegral() const
{
	return type_ == intValue  
		||  type_ == uintValue  
		||  type_ == booleanValue;
}


bool BSValue::isDouble() const
{
	return type_ == realValue;
}


bool BSValue::isNumeric() const
{
	return isIntegral() || isDouble();
}


bool BSValue::isString() const
{
	return type_ == stringValue;
}


bool BSValue::isArray() const
{
	return type_ == nullValue  ||  type_ == arrayValue;
}


bool BSValue::isObject() const
{
	return type_ == nullValue  ||  type_ == objectValue;
}



bool BSValue::isConvertibleTo( ValueType other ) const
{
	switch ( type_ )
	{
	case nullValue:
		return true;
	case intValue:
		return ( other == nullValue  &&  value_.int_ == 0 )
			|| other == intValue
			|| ( other == uintValue  && value_.int_ >= 0 )
			|| other == realValue
			|| other == stringValue
			|| other == booleanValue;
	case uintValue:
		return ( other == nullValue  &&  value_.uint_ == 0 )
			|| ( other == intValue  && value_.uint_ <= (unsigned)maxInt )
			|| other == uintValue
			|| other == realValue
			|| other == stringValue
			|| other == booleanValue;
	case realValue:
		return ( other == nullValue  &&  value_.real_ == 0.0 )
			|| ( other == intValue  &&  value_.real_ >= minInt  &&  value_.real_ <= maxInt )
			|| ( other == uintValue  &&  value_.real_ >= 0  &&  value_.real_ <= maxUInt )
			|| other == realValue
			|| other == stringValue
			|| other == booleanValue;
	case booleanValue:
		return ( other == nullValue  &&  value_.bool_ == false )
			|| other == intValue
			|| other == uintValue
			|| other == realValue
			|| other == stringValue
			|| other == booleanValue;
	case stringValue:
		return other == stringValue
			|| ( other == nullValue  &&  (!value_.string_  ||  value_.string_[0] == 0) );
	case arrayValue:
		return other == arrayValue
			||  ( other == nullValue  &&  value_.array_->size() == 0 );
	case objectValue:
		return other == objectValue
			||  ( other == nullValue  &&  value_.map_->size() == 0 );
	default:
		JSON_ASSERT_UNREACHABLE;
	}
	return false; // unreachable;
}


/// Number of values in array or object
unsigned int BSValue::size() const
{
	switch ( type_ )
	{
	case nullValue:
	case intValue:
	case uintValue:
	case realValue:
	case booleanValue:
	case stringValue:
		return 0;

	case arrayValue:  // size of the array is highest index + 1
		//if ( !value_.map_->empty() )
		//{
		//	ObjectValues::const_iterator itLast = value_.map_->end();
		//	--itLast;
		//	return (*itLast).first.index()+1;
		//}
		//return 0;wangyan
		return int( value_.array_->size() );
		
	case objectValue:
		return int( value_.map_->size() );

	default:
		JSON_ASSERT_UNREACHABLE;
	}
	return 0; // unreachable;
}

bool BSValue::empty() const
{
	if ( isNull() || isArray() || isObject() )
		return size() == 0u;
	else
		return false;
}


bool BSValue::operator!() const
{
	return isNull();
}

void BSValue::clear()
{
	JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue  || type_ == objectValue );

	switch ( type_ )
	{

	case arrayValue:
		value_.array_->clear();
		break;
	case objectValue:
		value_.map_->clear();
		break;
	default:
		break;
	}
}

void BSValue::resize( unsigned int newSize )
{
	JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
	if ( type_ == nullValue )
		*this = BSValue( arrayValue );

	value_.array_->resize(newSize);

}


BSValue & BSValue::operator[]( unsigned int index )
{
	JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
	if ( type_ == nullValue )
		*this = BSValue( arrayValue );

	if(index < value_.array_->size() )
	{
		return value_.array_->at(index);
	}
	else
	{
		value_.array_->resize(index+1);
   		value_.array_->at(index) = null;
		return value_.array_->at(index);
	}

	JSON_ASSERT_UNREACHABLE;
}


const BSValue &BSValue::operator[]( unsigned int index ) const
{
	JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
	if ( type_ == nullValue )
		return null;

	if(index < value_.array_->size() )
	{
		return value_.array_->at(index);
	}
	else
	{
		value_.array_->resize(index+1);
		value_.array_->at(index) = null;
		return value_.array_->at(index);
	}
	JSON_ASSERT_UNREACHABLE;

}


BSValue &BSValue::operator[]( const char *key )
{
	return resolveReference( key);
}


BSValue &BSValue::resolveReference( const char *key )
{
	JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
	if ( type_ == nullValue )
		*this = BSValue( objectValue );

	ObjectValues::iterator it = value_.map_->find(std::string(key));
	if ( it != value_.map_->end()  )
		return (*it).second;

	ObjectValues::value_type defaultValue( std::string(key), null );
	it = value_.map_->insert( it, defaultValue );
	BSValue &bsvalue = (*it).second;
	return bsvalue;

}

BSValue BSValue::get( unsigned int index, const BSValue &defaultValue ) const
{
	const BSValue *value = &((*this)[index]);
	return value == &null ? defaultValue : *value;
}

bool BSValue::isValidIndex( unsigned int index ) const
{
	return index < size();
}


const BSValue &BSValue::operator[]( const char *key ) const
{
	JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
	if ( type_ == nullValue )
		return null;

	ObjectValues::const_iterator it = value_.map_->find( std::string(key) );
	if ( it == value_.map_->end() )
		return null;
	return (*it).second;

}


BSValue &BSValue::operator[]( const std::string &key )
{
	return (*this)[ key.c_str() ];
}


const BSValue &BSValue::operator[]( const std::string &key ) const
{
	return (*this)[ key.c_str() ];
}


BSValue &BSValue::append( const BSValue &value )
{
	return (*this)[size()] = value;
}


BSValue BSValue::get( const char *key, 
	const BSValue &defaultValue ) const
{
	const BSValue *value = &((*this)[key]);
	return value == &null ? defaultValue : *value;
}


BSValue BSValue::get( const std::string &key,
	const BSValue &defaultValue ) const
{
	return get( key.c_str(), defaultValue );
}


BSValue BSValue::removeMember( const char* key )
{
	JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
	if ( type_ == nullValue )
		return null;


	ObjectValues::iterator it = value_.map_->find( std::string(key) );
	if ( it == value_.map_->end() )
		return null;
	BSValue old(it->second);
	value_.map_->erase(it);
	return old;

}

BSValue BSValue::removeMember( const std::string &key )
{
	return removeMember( key.c_str() );
}


bool  BSValue::isMember( const char *key ) const
{
	const BSValue *value = &((*this)[key]);
	return value != &null;
}


bool BSValue::isMember( const std::string &key ) const
{
	return isMember( key.c_str() );
}

BSValue::Members BSValue::getMemberNames() const
{
	JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
	if ( type_ == nullValue )
		return BSValue::Members();
	Members members;
	members.reserve( value_.map_->size() );

	ObjectValues::const_iterator it = value_.map_->begin();
	ObjectValues::const_iterator itEnd = value_.map_->end();
	for ( ; it != itEnd; ++it )
		members.push_back( std::string( (*it).first.c_str() ) );

	return members;
}
